package org.jsola.hr.service.impl;

import org.jsola.common.DateKit8;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.jsola.common.DateKit8;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.task.TaskKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ICompanySaleServerDAO;
import org.jsola.hr.dto.CompanySaleServerAddDTO;
import org.jsola.hr.dto.CompanySaleServerUpdateDTO;
import org.jsola.hr.dto.TaskAddDTO;
import org.jsola.hr.entity.CompanySaleServerDO;
import org.jsola.hr.provider.INoticeProviderService;
import org.jsola.hr.query.CompanySaleServerQuery;
import org.jsola.hr.service.ICompanySaleServerService;
import org.jsola.hr.vo.CompanySaleServerListVO;
import org.jsola.hr.vo.CompanySaleServerVO;
import org.jsola.hr.vo.HrNoticeDateSettingVO;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.notice.vo.NoticeRuleSettingVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用工单位服务
 *
 * @author zhr
 */
@Service("hrCompanySaleServerServiceImpl")
public class CompanySaleServerServiceImpl implements ICompanySaleServerService {

    @Autowired
    private ICompanySaleServerDAO companySaleServerDAO;

    @Autowired
    private TaskKit taskKit;

    @Autowired
    private INoticeProviderService noticeProviderService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanySaleServerVO save(CompanySaleServerAddDTO companySaleServerAddDTO, TokenUser tokenUser) {
        // 转DO
        CompanySaleServerDO companySaleServerDO = companySaleServerAddDTO.to(CompanySaleServerDO.class);
        // 保存
        companySaleServerDO = save(companySaleServerDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return companySaleServerDO.to(CompanySaleServerVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(CompanySaleServerUpdateDTO companySaleServerUpdateDTO, TokenUser tokenUser) {
        //转DO
        CompanySaleServerDO companySaleServerDO = companySaleServerUpdateDTO.to(CompanySaleServerDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(companySaleServerDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... companySaleServerIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) companySaleServerIds);
    }


    @Override
    public CompanySaleServerVO selectById(String companySaleServerId, String siteId) {
        CompanySaleServerDO companySaleServerDO = selectDOById(companySaleServerId, siteId);
        if (companySaleServerDO == null) {
            return null;
        }
        return companySaleServerDO.to(CompanySaleServerVO.class);
    }

    @Override
    public List<CompanySaleServerListVO> select(CompanySaleServerQuery companySaleServerQuery, String siteId) {
        List<CompanySaleServerDO> companySaleServerDOList = selectDO(companySaleServerQuery, siteId);
        if (CollectionUtils.isEmpty(companySaleServerDOList)) {
            return companySaleServerDOList == null ? null : new ArrayList<>();
        }
        return companySaleServerDOList.stream()
                .map(companySaleServerDO -> companySaleServerDO.to(CompanySaleServerListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(CompanySaleServerQuery companySaleServerQuery, String siteId) {
        Example example = buildExample(companySaleServerQuery, siteId);
        return companySaleServerDAO.selectCountByExample(example);
    }

    @Override
    public Page<CompanySaleServerListVO> selectPage(CompanySaleServerQuery companySaleServerQuery, String siteId) {
        Example example = buildExample(companySaleServerQuery, siteId);
        Page<CompanySaleServerDO> page = companySaleServerDAO.selectPageByExample(example,
                companySaleServerQuery.getPageNo(),
                companySaleServerQuery.getPageSize());

        return page.to(CompanySaleServerListVO.class);
    }

    @Override
    public CompanySaleServerDO selectDOById(String companySaleServerId, String siteId) {
        return listById(companySaleServerId, siteId);
    }

    @Override
    public List<CompanySaleServerDO> selectDO(CompanySaleServerQuery companySaleServerQuery, String siteId) {
        Example example = buildExample(companySaleServerQuery, siteId);
        return companySaleServerDAO.selectByExample(example);
    }

    @Override
    public List<CompanySaleServerDO> selectCompanyServerList(String companyId, String siteId) {
        Example example = new Example(CompanySaleServerDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", siteId);
        example.orderBy("serverBeginTime");
        return companySaleServerDAO.selectByExample(example);
    }

    @Override
    public List<CompanySaleServerDO> selectByCompanyIdList(List<String> companyIdList, String siteId) {
        Example example = new Example(CompanySaleServerDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("companyId", companyIdList)
                .andEqualTo("siteId", siteId);
        example.orderBy("serverBeginTime");
        return companySaleServerDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<CompanySaleServerDO> bachSave(List<CompanySaleServerAddDTO> companySaleServerList, TokenUser tokenUser) {
        List<CompanySaleServerDO> saveList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(companySaleServerList)) {
            List<CompanySaleServerDO> insertList = companySaleServerList
                    .stream()
                    .map(companySaleUser -> {
                        CompanySaleServerDO companySaleServer = companySaleUser.to(CompanySaleServerDO.class);
                        if (ObjectUtils.isEmpty(companySaleUser.getServerBeginTime())) {
                            throw new ParamException("服务开始时间为空");
                        }
                        if (ObjectUtils.isEmpty(companySaleUser.getServerEndTime())) {
                            throw new ParamException("服务结束时间为空");
                        }
                        companySaleServer.setId(UUID.randomUUID().toString().replace("-", "").toUpperCase());
                        companySaleServer.preInsert(tokenUser.getUserId());
                        companySaleServer.setSiteId(tokenUser.getSiteId());
                        saveList.add(companySaleServer);
                        return companySaleServer;
                    }).collect(Collectors.toList());
            companySaleServerDAO.insertListAndSetId(insertList);
        }
        return saveList;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void addServetTask(List<CompanySaleServerDO> serverList, String companyId, TokenUser tokenUser) {
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.JF_CONTRACT, companyId);
        if (ObjectUtils.isEmpty(ruleSettingVO) || !ruleSettingVO.getEnableStatus()) {
            return;
        }
        HrNoticeDateSettingVO dateSetting = JSON
                .parseObject(ruleSettingVO.getReceiveDateJson(), HrNoticeDateSettingVO.class);
        List<TaskAddDTO> taskAddDTOList = new ArrayList<>();
        for (CompanySaleServerDO companySaleServer : serverList) {
            Date serverEndTime = companySaleServer.getServerEndTime();
            // 过期的不添加
            if (DateKit8.getStartTime(new Date()).after(serverEndTime)) {
                continue;
            }
            // 1是当天提醒  else是提前n天
            Date runDate;
            String appointTime = dateSetting.getAppointTime();
            if (ruleSettingVO.getReceiveDateType() == 1) {
                runDate = DateKit8.parseDateTime(DateKit8
                        .format2Date(serverEndTime) + " " + appointTime);
            } else {
                runDate = DateKit8.parseDateTime(DateKit8.format2Date(DateKit8
                        .addDays(serverEndTime, dateSetting.getNumber() * -1L)) + " " + appointTime);
            }
            TaskAddDTO taskAdd = new TaskAddDTO();
            taskAdd.setSubjectType("jfContract");
            taskAdd.setSubjectId(companySaleServer.getId());
            taskAdd.setDescription("甲方端合同提醒");
            taskAdd.setRunBeanName("hrCompanySaleServerServiceImpl");
            taskAdd.setRunType(companyId);
            taskAdd.setRunDate(runDate);
            taskAdd.setStatus(false);
            taskAddDTOList.add(taskAdd);
        }
        taskKit.addTaskList(taskAddDTOList, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteFromCompany(String companyId, TokenUser tokenUser) {
        CompanySaleServerDO updateTemplate = new CompanySaleServerDO();
        updateTemplate.setValid(false);
        Example example = new Example(CompanySaleServerDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        companySaleServerDAO.updateByExampleSelective(updateTemplate, example);
    }

    @Override
    public void checkServerTime(List<CompanySaleServerAddDTO> companySaleServerList) {
        if (CollectionUtils.isEmpty(companySaleServerList)) {
            return;
        }
        // 以开始时间排序
        companySaleServerList = companySaleServerList.stream()
                .sorted(Comparator.comparing(CompanySaleServerAddDTO::getServerBeginTime))
                .collect(Collectors.toList());
        // 排序完之后,以上一个的结束时间比较下一个的开始时间,如果[结束时间 >= 开始时间]说明时间有重叠
        Date compareDate = null;
        for (CompanySaleServerAddDTO companySaleServer : companySaleServerList) {
            if (ObjectUtils.isEmpty(compareDate)) {
                compareDate = companySaleServer.getServerEndTime();
                continue;
            }
            if (compareDate.compareTo(companySaleServer.getServerBeginTime()) >= 0) {
                throw new ParamException("所选时间区间有重叠部分");
            } else {
                compareDate = companySaleServer.getServerEndTime();
            }
        }
    }

    /**
     * 判断用工单位是否处于合同有效期内,
     * 没有设置过合同有效期：返true,在有效期内
     * 设置过多条合同，只要有一条时间区间包含当前时间，就返回true,在有效期内
     * 其他场景，返回false,处于有效期外*
     * @param companyId
     * @param tokenUser
     * @return
     */
    @Override
    public Boolean findContractStatus(String companyId, TokenUser tokenUser) {
        Example example = new Example(CompanySaleServerDO.class);
        example.and().andEqualTo("companyId",companyId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        List<CompanySaleServerDO> list = companySaleServerDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return true;
        }
        LocalDate now = LocalDate.now();
        for (CompanySaleServerDO companySaleServerDO : list) {
            LocalDate beign = DateKit8.toLocalDate(companySaleServerDO.getServerBeginTime());
            LocalDate end = DateKit8.toLocalDate(companySaleServerDO.getServerEndTime());
            if (beign.compareTo(now) <= 0 && now.compareTo(end) <= 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据查询参数，构建example
     *
     * @param companySaleServerQuery 查询参数
     * @param siteId                 所属站点id
     * @return example
     */
    private Example buildExample(CompanySaleServerQuery companySaleServerQuery, String siteId) {
        Example example = new Example(CompanySaleServerDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        // 排序
        ExampleKit.setExampleOrder(example, companySaleServerQuery.getOrders());
        return example;
    }
}




